AWS IoT Analytics のデータストアでカスタムパーティションがサポートされました
先日、AWS IoT Analytics のアップデートでデータストアのカスタムパーティションが利用できるようになりました。
何がうれしいの?
これまでは、ユーザー側でパーティションを指定することができず、「1日」という固定の設定になっていました。そのため 1 時間分のデータだけクエリを実行したい場合でも無駄なスキャンコストが発生していました。
今回のアップデートで、パーティションを小さく分割できるようになったので、次のようなメリットが出てきました。
- スキャンするデータ量が少なくなるので利用料金を抑えられる
- データセットのスキャンコストの削減
- スキャンサイズが少なくなるのでクエリの実行パフォーマンスが上がる
やってみた
前提
今回は既存のデータフロー(チャネル, パイプライン, データストア)を利用します。既にあるデータストアに対してパーティション設定の変更はできないので、今回はデータストアを作り直しています。
下記では、既存のデータストアを一度削除して新たに作成しています。
既存のパイプラインをそのまま使いたかったので、「データストアID」は削除したものと同名とします。
データストアのストレージや IAM Role も既存のデータストアで使っていたものを指定しています。
データフォーマットも以前と同じままとします。
次の画面でようやくカスタムパーティションの設定を行います。「カスタムパーティションの有効化」 にチェックを入れます。データソースとして既存のチャネルを選択しました。
既存のデータソースを選択した状態で「Sample attributes」 をクリックすると、すでにチャネルに入っているデータがサンプルとして表示されます。
サンプルデータからカスタムパーティションのディメンションに使う項目にチェックを入れます。今回は timestamp
という項目を使おうと思うので、上部のプルダウンから Add as timestamp partition を選択します。
カスタムパーティションを指定できたら次のような画面が現れます。Attribute name
には先ほど選択したサンプルデータのカラム(timestamp)が自動的に設定されます。今回はタイムスタンプをカスタムパーティションとして設定したのでPartition Type
の欄も自動的に入力されました。
Timestamp format
はサンプルデータに合わせてyyyy-MM-dd HH:mm:ss
を指定しています。なお、Dimension name
はタイムスタンプをパーティションとして指定すると自動的に設定されます。
最後のレビュー画面で設定内容を確認してデータセットの作成を実行します。
確認用のデバイスデータを IoT Analytics に送る
次にデータを送ってみます。今回は 大量にデータを送りたかったのでbasic ingest
を使ってデータを IoT Analytics に送信しました。
データの送信は以前ご紹介した 「MQTT X」というクライアントツールのスクリプト機能を使いました。スクリプトでランダムデータを生成して10 秒間隔でデータを送っています。
「MQTT X」の使い方については下記のブログをご参照下さい。
「MQTT X」で利用した JavaScript は下記になります。(コーディングは不慣れなため稚拙なコードである点はご容赦ください)
function random(min, max) { return Math.round(Math.random() * (max - min)) + min } var d = new Date(); var year = d.getFullYear(); //var month = d.getMonth() + 1; var month = ("0"+(d.getMonth() + 1)).slice(-2); var day = d.getDate(); var hour = ( d.getHours() < 10 ) ? '0' + d.getHours() : d.getHours(); var min = ( d.getMinutes() < 10 ) ? '0' + d.getMinutes() : d.getMinutes(); var sec = ( d.getSeconds() < 10 ) ? '0' + d.getSeconds() : d.getSeconds(); function handlePayload(value) { let _value = value if (typeof value == 'string') { _value = JSON.parse(value) } _value.sub_metering_1 = random(10,30) _value.sub_metering_2 = random(20,40) _value.sub_metering_3 = random(20,40) _value.global_active_power = random(0,10) _value.global_reactive_power = random(10,30) _value.voltage = random(200,250) _value.timestamp = year + '-' + month + '-' + day + ' ' + hour + ':' + min + ':' + sec _value._id_ = 'KwW37jXxC' return JSON.stringify(_value, null, 2) } execute(handlePayload)
実際に送信されるデータは下記のようなものになります。
{ "sub_metering_1": 55, "sub_metering_2": 43, "sub_metering_3": 12, "global_active_power": 7, "global_reactive_power": 23, "timestamp": "2021-06-15 04:41:28", "voltage": 222, "_id_": "KwW37jXxC" }
カスタムパーティションの効果を確認する
繰り返しになりますが今回は次のようにデータを送ってみました。
- 200 Byte 程度のデータを 10 秒間隔で送信
- 送信したデータ総数は約3000件
- 途中で送信間隔を 1秒に変更して送っていました
データを送信後、AWS IoT Analytics のデータセットでクエリを実行してみます。スキャン期間を変えてクエリの実行時間に違いがあるか確認してみました。
16 時台のデータだけスキャン
次の SQLデータセットで指定したカスタムパーティションを使ってクエリを実行します。
SELECT * FROM mystore where __year = 2021 AND __month = 06 AND __day = 15 AND __hour = 16
17 時以降の全データをスキャン
少し変えて次の SQLデータセットで 17 時以降全てのデータを対象にクエリを実行してみます。
SELECT * FROM mystore where __year = 2021 AND __month = 06 AND __day = 15 AND __hour >= 17
スキャン時間の比較
「16時台」と「17 時以降全て」でクエリの実行時間は次のようになりました。
スキャン回数(回目) | 16時台のクエリ時間 | 17時以降のクエリ時間 |
---|---|---|
1 | 1535 ms | 1913 ms |
2 | 1550 ms | 2052 ms |
3 | 1435 ms | 2109 ms |
4 | 1291 ms | 2253 ms |
5 | 1467 ms | 2751 ms |
6 | 1838 ms | 2833 ms |
7 | 1485 ms | 2535 ms |
8 | 1487 ms | 2067 ms |
9 | 1689 ms | 1844 ms |
10 | 1416 ms | 2368 ms |
それぞれの平均は次のとおりです。
16時台のクエリ時間平均 | 17時以降のクエリ時間平均 |
---|---|
1519.3ms | 2272.5ms |
データ量が少ないので、大きな違いは確認できませんでしたがスキャンサイズが変わったことでクエリパフォーマンスの変化を確認することができたと思います。より大きなデータサイズ(数十GB〜やTBクラス)になると違いが顕著に現れるかと思います。
なお、比較に使ったクエリ時間はデータセットコンテンツに記載のものを採用しました。
補足 - データストアの S3 バケット構造
今回のようにタイムスタンプをカスタムパーティションとして作成した場合、データストアの S3 バケットは次のような構成になっていました。
└── your-datastore-bucket └── datastore └── your-data-store └── __dt=2021-06-15\ 00:00:00 └── __year=2021 └── __month=06 └── __day=15 └── __hour=20
最後に
今回はタイムスタンプを元にパーティションを指定しましたが、カスタム属性をパーティションとすることもできるようなので、後日試してみたいと思います。
以上です。